#
#   Game.py
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; version 2 of the License.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   Copyright
#   Author: Nicholas F. Hoover
#   Contributors: Salvatore S. Gionfriddo
#   Created: 2007.07.03
#   Last Modified: 2007.07.25
#

import pygame
import Messages, Spawner, EventHandler, GameObject
from Options import Options
from hud import Background, HUD
from hkm import HotKeyMenu, HotKeyMenuSystem
from GameObjectManager import GameObjectManager
from Level import Level
from Levels import Levels
from Statistics import Statistics


class Game(object):

    POINTS_PER_BASICKID = 500
    POINTS_PER_FASTKID = 600
    POINTS_PER_STRONGKID = 700
    POINTS_PER_FATKID = 500
    POINTS_PER_WEAKKID = 50

    POINTS_PER_POWERUP = -1000
    
    POINTS_PER_TICK = 1

    FPS = 30
    
    def __init__(self, screen, rManager, mission):
        self.screen = screen
        self.background = Background(self.screen, (0,0), self.screen.get_size())

        GameObject.RESOURCE_MANAGER = rManager #set the 'static' variable
        self.gameObjectManager = GameObjectManager(rManager)
        self.hud = HUD(self.screen)
        
        self.hkms = HotKeyMenuSystem(self.screen, (10,50), view_inventory=self.gameObjectManager.evilGreg.viewItemCount, use_inventory=self.gameObjectManager.evilGreg.useItem)
                
        self.clock = pygame.time.Clock()
        self.eventHandler = EventHandler.GameEventHandler(self)

        self.musicOn = False
        
        self.statTrackers = {
                        'Kills':self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL], self.getCurrentLevel),
                        'BasicKidKills':self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL, Statistics.BASICKID], self.getCurrentLevel),
                        'FastKidKills':self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL, Statistics.FASTKID], self.getCurrentLevel),
                        'StrongKidKills':self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL, Statistics.STRONGKID], self.getCurrentLevel),
                        'StrongKidKillsByPunch':self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL, Statistics.STRONGKID, Statistics.PUNCH], self.getCurrentLevel),
                        'FatKidKills':self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL, Statistics.FATKID], self.getCurrentLevel),
                        'FatKidsEaten':self.gameObjectManager.egStats.viewByLevelFunction([Statistics.EAT, Statistics.FAT_SOUL], self.getCurrentLevel),
                        'WeakKidKills':self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL, Statistics.WEAKKID], self.getCurrentLevel),
                        'TotalKills':self.gameObjectManager.egStats.viewFunction([Statistics.KILL]),
                        'Eaten': self.gameObjectManager.egStats.viewByLevelFunction([Statistics.EAT, Statistics.ENEMY], self.getCurrentLevel),
                        'KillsByPunch': self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL, Statistics.PUNCH], self.getCurrentLevel),
                        'KillsByKick': self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL, Statistics.KICK], self.getCurrentLevel),
                        'KillsByFlame': self.gameObjectManager.egStats.viewByLevelFunction([Statistics.KILL, Statistics.FLAME], self.getCurrentLevel),
                        'Time': self.gameObjectManager.egStats.viewByLevelFunction([Statistics.TIME], self.getCurrentLevel),
                        'TotalTime': self.gameObjectManager.egStats.viewFunction([Statistics.TIME]),
                        }
        self.spawnFunctions = {
                    'Kid': self.gameObjectManager.addKid,
                    'FastKid': self.gameObjectManager.addFastKid,
                    'FatKid': self.gameObjectManager.addFatKid,
                    'StrongKid': self.gameObjectManager.addStrongKid,
                    'WeakKid': self.gameObjectManager.addWeakKid,
                    'Pizza': self.gameObjectManager.addPizza,
                    'Drugs': self.gameObjectManager.addDrugs,
                    'Indian': self.gameObjectManager.addIndian,
                    'Tacos': self.gameObjectManager.addTacos,
                    }
        self.levelManager = Levels(self.statTrackers, self.spawnFunctions)
        self.mission = mission
        self.initLevels()
        self.reset()
        
    def setMission(self, mission):
        self.mission = mission
        self.initLevels()
        self.reset()

    def cancel(self):
        self.hkms.cancel()
        self.hkms_on = False
        
    def getCurrentLevel(self):
        return self.currentLevel
    
    def initLevels(self):
        self.levelManager.loadLevels(self.mission)
        self.levels = self.levelManager.getLevels()
        for i in range(1,len(self.levels)):
            self.gameObjectManager.egStats.addLevel()

        
    def nextLevel(self):
        if self.currentLevel + 1 < len(self.levels):
            self.currentLevel += 1
            self.gameObjectManager.setSpawners(self.levels[self.currentLevel].spawners)
            self.gameObjectManager.level += 1
            self.tintScreen()
            Messages.printLevel(self.screen, self.levels[self.currentLevel].name, self.levels[self.currentLevel].description)
            self.pauseIt(doTint = False)
        else:
            #Messages.printWin()
            #self.pauseIt()
            self.win = True
            self.quitGame()

    def isLevelComplete(self):
        return self.levels[self.currentLevel].isLevelComplete()
            
    def mainLoop(self):

        self.nextLevel()
        while self.gameObjectManager.evilGreg.isAlive() and not self.quit:
            if self.pause:
                self.pauseIt()
            self.clock.tick(self.FPS)
            self.eventHandler.doEvents(pygame.event.get())
            self.background.draw()
            self.gameObjectManager.update(self.screen)
            
            if self.isLevelComplete():
                self.nextLevel()
            (health, hunger, heartBurn, gas)  = self.gameObjectManager.evilGreg.getStats()
            totalKills = self.statTrackers["TotalKills"]()
            kills = self.statTrackers["Kills"]()
            self.hud.update(totalKills, kills, health, hunger, heartBurn, gas, self.levels[self.currentLevel].getGoalStatus(), self.clock.get_fps())
            self.hud.draw()
            
            if self.hkms.on:
                self.hkms.draw()
            
            pygame.display.flip()

        if not self.gameObjectManager.evilGreg.isAlive():
            #Do death sequence
            #This is a little bit #HACK
            self.background.draw()
            self.gameObjectManager.killEG(self.screen)
            self.hud.draw()
        elif self.quit:
            pass
    
    def reset(self):
        self.hud.reset()
        self.gameObjectManager.reset()
        self.done = False
        self.pause = False
        self.currentLevel = -1 # so can call next level to get to 0
        for level in self.levels:
            level.reset()
        self.quit = False
        self.win = False
        
    def pauseIt(self, doQuit = False, doTint = True):
        self.hud.draw()
        if doTint:
            self.tintScreen()
        if doQuit:
            Messages.printQuit(self.screen)
        else:
            Messages.printPaused(self.screen)
        pygame.display.flip()
        if Options.SOUND['MUSIC_ON']:
            pygame.mixer.music.set_volume(pygame.mixer.music.get_volume()/2.0)
            
        EventHandler.waitForKeyOrQuit(Options.CONTROLS['ENTER'], self.quitGame)
        self.pause = False
        self.gameObjectManager.evilGreg.clearNextAction()
            
        if Options.SOUND['MUSIC_ON']:
            pygame.mixer.music.set_volume(pygame.mixer.music.get_volume()*2.0)


    def getScore(self):        
        #KIDS
        basickid = (Game.POINTS_PER_BASICKID, self.gameObjectManager.egStats.view([Statistics.KILL, Statistics.BASICKID]), "Basic Kid")
        fastkid = (Game.POINTS_PER_FASTKID, self.gameObjectManager.egStats.view([Statistics.KILL, Statistics.FASTKID]), "Fast Kid")
        strongkid = (Game.POINTS_PER_STRONGKID, self.gameObjectManager.egStats.view([Statistics.KILL, Statistics.STRONGKID]), "Strong Kid")
        fatkid = (Game.POINTS_PER_FATKID, self.gameObjectManager.egStats.view([Statistics.KILL, Statistics.FATKID]), "Fat Kid")
        weakkid = (Game.POINTS_PER_WEAKKID, self.gameObjectManager.egStats.view([Statistics.KILL, Statistics.WEAKKID]), "Weak Kid")
        
        #TIME
        time = (Game.POINTS_PER_TICK, self.gameObjectManager.egStats.view([Statistics.TIME]), "Time Score")
        
        #POWERUPS
        powerup = (Game.POINTS_PER_POWERUP, self.gameObjectManager.egStats.view([Statistics.EAT, Statistics.POWERUP]), "Power Up Penalty")
        
        return [basickid, fastkid, strongkid, fatkid, weakkid, time, powerup]


    def toggleMusic(self):
        if Options.SOUND['MUSIC_ON']:
            pygame.mixer.music.pause()
        else:
            pygame.mixer.music.unpause()
        Options.SOUND['MUSIC_ON'] = not Options.SOUND['MUSIC_ON']



    def startMusic(self):
        self.musicOn = True
        pygame.mixer.music.play(-1)

    def tintScreen(self):
        tint = pygame.Surface(self.screen.get_size())
        tint.fill((0,0,0))
        tint.set_alpha(40)
        self.screen.blit(tint,(0,0))


    def quitGame(self):
        self.quit = True

